using JetBrains.Annotations;
using Stereotypes.Annotations;



namespace Fine.Collections.Const
{
    /// <summary>
    /// Prime numbers. Helps to select a prime number for a hash table.
    /// Interval: 17 .. 199999.
    /// </summary>
    [Service]
    public static class PrimeNumbers
    {
        private static readonly uint[] PrimeNumbersForHashContainersAsArray =
            {17, 53, 163, 499, 1499, 4507, 9001, 18013, 25411, 35831, 
             50503, 70001, 85009, 100003, 125003, 150001, 175003, 199999};


        /// <summary>
        /// Contains the set of prime numbers choosed for hash tables.
        /// </summary>
        [NotNull]
        public static readonly ConstSortSet<uint> PrimeHumbersForHashContainers =
            new ConstSortSet<uint>( 1,
                                    PrimeNumbersForHashContainersAsArray, 
                                    PrimeNumbersForHashContainersAsArray.Length,
                                    false, false, true );

        /// <summary>
        /// Selects the prime number from the <see cref="PrimeHumbersForHashContainers"/>
        /// that is the neares to the specified one.
        /// </summary>
        /// <param name="x">specified number for select the nearest prime number.</param>
        /// <returns>selected prime number.</returns>
        public static uint SelectRingPowerForContainer (uint x)
        {
            bool found;
            int nearestIndex;

            PrimeHumbersForHashContainers.Find(x, out found, out nearestIndex);

            if (found)
                return x;

            if (nearestIndex == PrimeHumbersForHashContainers.FirstIndex)
                return PrimeHumbersForHashContainers.First;

            if (nearestIndex > PrimeHumbersForHashContainers.LastIndex)
                return PrimeHumbersForHashContainers.Last;

            uint prime1 = PrimeHumbersForHashContainers[nearestIndex - 1],
                 prime2 = PrimeHumbersForHashContainers[nearestIndex];
            uint delta1 = x - prime1,
                 delta2 = prime2 - x;

            return delta1 <= delta2 ? prime1 : prime2;
        }

    }

}